package com.itstherules.jmsunit.expectation;

import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.jms.JMSException;
import javax.jms.Message;

import org.junit.Assert;

import com.itstherules.jmsunit.expectation.JmsExpectation;
import com.itstherules.jmsunit.headers.JmsHeadersDefinition;

public final class HeadersEqualsExpectation implements JmsExpectation {

	private final JmsHeadersDefinition expectedDefinition;

	public HeadersEqualsExpectation(JmsHeadersDefinition expectedDefinition) {
		this.expectedDefinition = expectedDefinition;
	}

	public final void compute(Message actual) throws AssertionError {
		Map<String, String> expectedHeaders = expectedDefinition.getHeaders();
		Map<String, String> actualHeaders = collectHeaders(actual);

		for (String expectedKey : expectedHeaders.keySet()) {
			String expectedValue = expectedHeaders.get(expectedKey);
			String actualValue = actualHeaders.get(expectedKey);
			Assert.assertEquals("The JMSHeader value for the message "
					+ expectedDefinition.getName() + " (header key is "
					+ expectedKey + ") is not equal", expectedValue,
					actualValue);
		}
	}

	@SuppressWarnings("unchecked")
	private Map<String, String> collectHeaders(Message actual) {
		Map<String, String> headers = new LinkedHashMap<String, String>();
		Enumeration<String> propertyNames;
		try {
			propertyNames = actual.getPropertyNames();
			while (propertyNames.hasMoreElements()) {
				String name = propertyNames.nextElement();
				String value = actual.getStringProperty(name);
				headers.put(name, value);
			}
			
			if (actual.getJMSReplyTo() != null) {
				headers.put("JMSReplyTo", actual.getJMSReplyTo().toString() );
			}
			if (actual.getJMSCorrelationID() != null) {
				headers.put("JMSCorrelationID", actual.getJMSCorrelationID());
			}  
			if (actual.getJMSMessageID() != null) {
				headers.put("JMSMessageID", actual.getJMSMessageID());
			} 
			if (actual.getJMSType() != null) {
				headers.put("JMSType", actual.getJMSType());
			} 
			if (actual.getJMSDestination() != null) {
				headers.put("JMSDestination", actual.getJMSDestination().toString());
			} 
			
		} catch (JMSException e) {
			throw new RuntimeException(e);
		}

		return headers;
	}
	
	@Override
	public String toString() {
		return "Headers equals expectation (expected is "+ expectedDefinition+")";
	}
}